home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / HAS Other Source / WASTE 1.3a4 Distribution / WASTE 1.3a4 / Source / WEObjects.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-04  |  10.1 KB  |  434 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WEObjects.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Embedded Objects
  6.  *
  7.  *  Copyright (c) 1993-1997 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. #if WASTE_OBJECTS
  18.  
  19. // static variables
  20.  
  21. static WEOHTableHandle _weGlobalObjectHandlerTable;
  22.  
  23. pascal FlavorType WEGetObjectType(WEObjectDescHandle hObjectDesc)
  24. {
  25.     return (*hObjectDesc)->objectType;
  26. }
  27.  
  28. pascal Handle WEGetObjectDataHandle(WEObjectDescHandle hObjectDesc)
  29. {
  30.     return (*hObjectDesc)->objectDataHandle;
  31. }
  32.  
  33. pascal Point WEGetObjectSize(WEObjectDescHandle hObjectDesc)
  34. {
  35.     return (*hObjectDesc)->objectSize;
  36. }
  37.  
  38. pascal WEHandle WEGetObjectOwner(WEObjectDescHandle hObjectDesc)
  39. {
  40.     return (*hObjectDesc)->objectOwner;
  41. }
  42.  
  43. pascal SInt32 WEGetObjectRefCon(WEObjectDescHandle hObjectDesc)
  44. {
  45.     return (*hObjectDesc)->objectRefCon;
  46. }
  47.  
  48. pascal void WESetObjectRefCon(WEObjectDescHandle hObjectDesc, SInt32 refCon)
  49. {
  50.     (*hObjectDesc)->objectRefCon = refCon;
  51. }
  52.  
  53. pascal SInt32 _WELookupObjectType(FlavorType objectType, WEOHTableHandle hTable)
  54. {
  55.     // look for a WEOHTableEntry record for the specified object kind
  56.     // in the given object handler table
  57.  
  58.     SInt32 nEntries, index;
  59.     WEOHTableEntry *pTable;
  60.  
  61.     // do nothing if the Object Handler Table has not been inited yet
  62.     if (hTable == nil)
  63.     {
  64.         return kUnknownObjectType;
  65.     }
  66.  
  67.     // calculate entry count
  68.     nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableEntry);
  69.  
  70.     // scan the Object Handler Table looking for a type match
  71.     pTable = *hTable;
  72.     for ( index = 0; index < nEntries; index++ )
  73.     {
  74.         if (pTable->objectType == objectType)
  75.         {
  76.             return index;
  77.         }
  78.         pTable++;
  79.     }
  80.  
  81.     return kUnknownObjectType;
  82. }
  83.  
  84. pascal OSErr _WEGetIndObjectType(SInt32 index, FlavorType *objectType, WEHandle hWE)
  85. {
  86.     WEOHTableHandle hTable;
  87.     SInt32 nEntries;
  88.  
  89.     *objectType = 0L;
  90.  
  91.     // index must be non-negative
  92.     if (index < 0)
  93.     {
  94.         return weUnknownObjectTypeErr;
  95.     }
  96.  
  97.     // calculate number of entries in the instance-specific handler table
  98.     nEntries = 0;
  99.     hTable = (*hWE)->hObjectHandlerTable;
  100.     if (hTable != nil)
  101.     {
  102.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableEntry);
  103.     }
  104.  
  105.     // low indices refer to the instance-specific handler table
  106.     if (index < nEntries)
  107.     {
  108.         *objectType = (*hTable)[index].objectType;
  109.         return noErr;
  110.     }
  111.     // indices above that refer to the global handler table
  112.     index -= nEntries;
  113.  
  114.     // calculate number of entries in the global handler table
  115.     nEntries = 0;
  116.     hTable = _weGlobalObjectHandlerTable;
  117.     if (hTable != nil)
  118.     {
  119.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableEntry);
  120.     }
  121.  
  122.     // return an error code if index is too large
  123.     if (index >= nEntries)
  124.     {
  125.         return weUnknownObjectTypeErr;
  126.     }
  127.  
  128.     *objectType = (*hTable)[index].objectType;
  129.  
  130.     return noErr;
  131. }
  132.  
  133. pascal OSErr _WENewObject(FlavorType objectType, Handle objectDataHandle, WEHandle hWE,
  134.                     WEObjectDescHandle *hObjectDesc)
  135. {
  136.     WEObjectDesc *pDesc;
  137.     WEOHTableHandle hTable;
  138.     SInt32 index;
  139.     OSErr err;
  140.  
  141.     *hObjectDesc = nil;
  142.  
  143.     // first look up the specified object type in the instance-specific handler table
  144.     hTable = (*hWE)->hObjectHandlerTable;
  145.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  146.     {
  147.         // no match: try with the global handler table
  148.         hTable = _weGlobalObjectHandlerTable;
  149.         if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  150.         {
  151.             hTable = nil;
  152.         }
  153.     }
  154.  
  155.     // create a new relocatable block to hold the object descriptor
  156.     if ((err = _WEAllocate(sizeof(WEObjectDesc), kAllocClear, (Handle *)hObjectDesc)) != noErr)
  157.     {
  158.         return err;
  159.     }
  160.  
  161.     // lock it down
  162.     HLock((Handle) *hObjectDesc);
  163.     pDesc = (WEObjectDesc *) **hObjectDesc;
  164.  
  165.     // fill in the object descriptor
  166.     pDesc->objectType = objectType;
  167.     pDesc->objectDataHandle = objectDataHandle;
  168.     pDesc->objectSize.v = kDefaultObjectHeight;
  169.     pDesc->objectSize.h = kDefaultObjectWidth;
  170.     pDesc->objectTable = hTable;
  171.     pDesc->objectIndex = index;
  172.     pDesc->objectOwner = hWE;
  173.  
  174.     if (hTable != nil)
  175.     {
  176.         WENewObjectUPP newHandler = (*hTable)[index].newHandler;
  177.         pDesc->objectRefCon = (*hTable)[index].refCon;
  178.  
  179.         // call the new handler, if any
  180.         if (newHandler != nil)
  181.         {
  182.             if ((err = CallWENewObjectProc(&pDesc->objectSize, *hObjectDesc, newHandler)) != noErr)
  183.             {
  184.                 _WEForgetHandle((Handle *) hObjectDesc);
  185.                 return err;
  186.             }
  187.         }
  188.     }
  189.  
  190.     // unlock the object descriptor
  191.     HUnlock((Handle) *hObjectDesc);
  192.  
  193.     // clear result code
  194.     return noErr;
  195. }
  196.  
  197. pascal OSErr _WEFreeObject(WEObjectDescHandle hObjectDesc)
  198. {
  199.     WEObjectDesc *pDesc;
  200.     OSErr err = noErr;
  201.  
  202.     // sanity check: do nothing if we have a null descriptor handle
  203.     if (hObjectDesc == nil)
  204.     {
  205.         return nilHandleErr;
  206.     }
  207.  
  208.     // lock the descriptor record
  209.     HLock((Handle)hObjectDesc);
  210.     pDesc = *hObjectDesc;
  211.  
  212.     if (pDesc->objectTable != nil)
  213.     {
  214.         WEDisposeObjectUPP freeHandler = (*pDesc->objectTable)[pDesc->objectIndex].freeHandler;
  215.  
  216.         // call the dispose handler, if any
  217.         if (freeHandler != nil)
  218.         {
  219.             err = CallWEDisposeObjectProc(hObjectDesc, freeHandler);
  220.             pDesc->objectDataHandle = nil;
  221.         }
  222.     }
  223.  
  224.     // if object kind is unknown or there's no custom dispose handler, use DisposeHandle
  225.     _WEForgetHandle(&pDesc->objectDataHandle);
  226.  
  227.     // finally, dispose of the object descriptor itself
  228.     DisposeHandle((Handle)hObjectDesc);
  229.  
  230.     return err;
  231. }
  232.  
  233. pascal OSErr _WEDrawObject(WEObjectDescHandle hObjectDesc)
  234. {
  235.     WEObjectDesc *pDesc;
  236.     Rect destRect;
  237.     PenState state;
  238.     Boolean saveDescLock;
  239.     OSErr err = noErr;
  240.  
  241.     // lock the object descriptor
  242.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  243.     pDesc = *hObjectDesc;
  244.  
  245.     // get current pen state
  246.     // state.pnLoc has already been set to the bottom left of the rectangle to draw
  247.     GetPenState(&state);
  248.  
  249.     // calculate the new pen position
  250.     state.pnLoc.h += pDesc->objectSize.h;
  251.  
  252.     // calculate the destination rectangle
  253.     * (SInt32 *) (&topLeft(destRect)) = DeltaPoint(state.pnLoc, pDesc->objectSize);
  254.     botRight(destRect) = state.pnLoc;
  255.  
  256.     if (pDesc->objectTable != nil)
  257.     {
  258.         WEDrawObjectUPP drawHandler = (*pDesc->objectTable)[pDesc->objectIndex].drawHandler;
  259.  
  260.         // call the drawing handler, if any
  261.         if (drawHandler != nil)
  262.         {
  263.             err = CallWEDrawObjectProc(&destRect, hObjectDesc, drawHandler);
  264.         }
  265.     }
  266.     else
  267.     {
  268.         // if this object kind was not registered, draw an empty frame
  269.         PenNormal();
  270.         FrameRect(&destRect);
  271.     }
  272.  
  273.     // restore original pen state, advancing the pen position by the object width
  274.     SetPenState(&state);
  275.  
  276.     // unlock the object descriptor
  277.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  278.  
  279.     return err;
  280. }
  281.  
  282. pascal Boolean _WEClickObject(Point hitPt, EventModifiers modifiers, UInt32 clickTime,
  283.                                 WEObjectDescHandle hObjectDesc)
  284. {
  285.     WEObjectDesc *pDesc;
  286.     Boolean saveDescLock;
  287.     Boolean clickHandled = false;
  288.  
  289.     // lock the object descriptor
  290.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  291.     pDesc = *hObjectDesc;
  292.  
  293.     if (pDesc->objectTable != nil)
  294.     {
  295.         WEClickObjectUPP clickHandler = (*pDesc->objectTable)[pDesc->objectIndex].clickHandler;
  296.  
  297.         // call the click handler, if any
  298.         if (clickHandler != nil)
  299.         {
  300.             clickHandled = CallWEClickObjectProc(hitPt, modifiers, clickTime, hObjectDesc, clickHandler);
  301.         }
  302.     }
  303.  
  304.     // unlock the object descriptor
  305.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  306.  
  307.     return clickHandled;
  308. }
  309.  
  310. pascal OSErr _WEStreamObject(SInt16 destKind, FlavorType *theType,
  311.                 Handle *theData, Boolean *canDisposeData, WEObjectDescHandle hObjectDesc)
  312. {
  313.     WEObjectDesc *pDesc;
  314.     Boolean saveDescLock;
  315.     OSErr err = weNotHandledErr;
  316.  
  317.     *canDisposeData = true;
  318.  
  319.     // lock the object descriptor
  320.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  321.     pDesc = *hObjectDesc;
  322.  
  323.     if (pDesc->objectTable != nil)
  324.     {
  325.         WEStreamObjectUPP streamHandler = (*pDesc->objectTable)[pDesc->objectIndex].streamHandler;
  326.  
  327.         // call the stream handler, if any
  328.         if (streamHandler != nil)
  329.         {
  330.             err = CallWEStreamObjectProc(destKind, theType, *theData, hObjectDesc, streamHandler);
  331.         }
  332.     }
  333.  
  334.     if (err == weNotHandledErr)
  335.     {
  336.         // default streaming behavior
  337.         _WEForgetHandle(theData);
  338.         *canDisposeData = false;
  339.         *theType = pDesc->objectType;
  340.         *theData = pDesc->objectDataHandle;
  341.         err = noErr;
  342.     }
  343.  
  344.     // unlock the object descriptor
  345.     _WESetHandleLock((Handle) hObjectDesc, saveDescLock);
  346.  
  347.     return err;
  348. }
  349.  
  350. pascal OSErr WEInstallObjectHandler(FlavorType objectType, WESelector handlerSelector,
  351.                 UniversalProcPtr handler, WEHandle hWE)
  352. {
  353.     WEOHTableHandle hTable;
  354.     SInt32 index;
  355.     WEOHTableEntry entry;
  356.     OSErr err;
  357.  
  358.     // if hWE is nil, install the handler in the global handler table,
  359.     // otherwise install the handler in the instance-specific handler table
  360.     if (hWE == nil)
  361.     {
  362.         hTable = _weGlobalObjectHandlerTable;
  363.     }
  364.     else
  365.     {
  366.         hTable = (*hWE)->hObjectHandlerTable;
  367.     }
  368.  
  369.     // create the handler table, if it doesn't exist
  370.     if (hTable == nil)
  371.     {
  372.         hTable = (WEOHTableHandle) NewHandle(0);
  373.         if ((err = MemError()) != noErr)
  374.         {
  375.             return err;
  376.         }
  377.         if (hWE == nil)
  378.         {
  379.             _weGlobalObjectHandlerTable = hTable;
  380.         }
  381.         else
  382.         {
  383.             (*hWE)->hObjectHandlerTable = hTable;
  384.         }
  385.     }
  386.  
  387.     // look for the entry corresponding to the specified object type
  388.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  389.     {
  390.         BLOCK_CLR(entry);
  391.         entry.objectType = objectType;
  392.  
  393.         // previously unknown object type: append a new entry at the end of the handler table
  394.         index = GetHandleSize((Handle) hTable) / sizeof(WEOHTableEntry);
  395.         if ((err = _WESplice((Handle) hTable, &entry, sizeof(entry), -1)) != noErr)
  396.         {
  397.             return err;
  398.         }
  399.     }
  400.  
  401.     // install the handler
  402.     return _WESetField(_weObjectHandlerSelectorTable, handlerSelector, (SInt32 *) &handler, *hTable + index);
  403. }
  404.  
  405. pascal OSErr WEGetObjectHandler(FlavorType objectType, WESelector handlerSelector,
  406.                 UniversalProcPtr *handler, WEHandle hWE)
  407. {
  408.     WEOHTableHandle hTable;
  409.     SInt32 index;
  410.  
  411.     // if hWE is nil, look for the handler in the global handler table,
  412.     // otherwise look in the instance-specific handler table
  413.     if (hWE == nil)
  414.     {
  415.         hTable = _weGlobalObjectHandlerTable;
  416.     }
  417.     else
  418.     {
  419.         hTable = (*hWE)->hObjectHandlerTable;
  420.     }
  421.  
  422.     // first make sure the handler table exists
  423.     // then check to see if an entry for the specified object type is present
  424.     if ((hTable == nil) || ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType))
  425.     {
  426.         return weUnknownObjectTypeErr;
  427.     }
  428.  
  429.     // return the address of the specified handler
  430.     return _WEGetField(_weObjectHandlerSelectorTable, handlerSelector, (SInt32 *) handler, *hTable + index);
  431. }
  432.  
  433. #endif  // WASTE_OBJECTS
  434.